package com.nxs.dataPackage.coder;

import com.nxs.dataPackage.constant.ConstantValue;
import com.nxs.dataPackage.model.Request;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;

/**
 * @Description: 数据包格式
 * +--------+--------+--------+--------+--------+
 * |  包头  | 模块号  | 命令号 |  长度  |  数据  |
 * +--------+--------+--------+--------+--------+
 * 包头：4字节
 * 模块号：2字节short
 * 命令号：2字节short
 * 长度：4字节（数据部分的字节长度）
 */
public class RequestDecoder extends FrameDecoder{

    //数据包基本长度
    private static int BASE_LENGTH = 4 + 2 + 2 + 4;

    @Override
    protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
        //可读长度必须大于基本长度
        if(buffer.readableBytes() >= BASE_LENGTH){
            //防止socket字节流攻击
            if(buffer.readableBytes() > 2048){
                buffer.skipBytes(buffer.readableBytes());
            }

            int beginReader; // 包头开始的位置
            while (true){
                beginReader = buffer.readerIndex();
                buffer.markReaderIndex();
                if(buffer.readInt() == ConstantValue.FLAG){
                    break;
                }

                //未读到包头，略过一个字节
                buffer.resetReaderIndex();
                buffer.readByte();

                //长度又变得不满足
                if(buffer.readableBytes() < BASE_LENGTH) {
                    return null;
                }
            }
            //模块号
            short module = buffer.readShort();
            //命令号
            short cmd = buffer.readShort();
            //长度
            int length = buffer.readInt();

            //判断请求数据包数据是否到齐
            if(buffer.readableBytes() < length){
                //还原读指针
                buffer.readerIndex(beginReader);
                return null;
            }

            //读取data数据
            byte[] data = new byte[length];
            buffer.readBytes(data);

            Request request = new Request();
            request.setModule(module);
            request.setCmd(cmd);
            request.setData(data);

            //继续往下传递
            return request;
        }
        return null;
    }
}
